package main

import (
	"fmt"
	"runtime/debug"
	"sync"
	"time"

	myactor "gitee.com/nggs/actor"
	"gitee.com/nggs/protoactor-go/actor"
	"gitee.com/nggs/util"
)

const entityName = "entity"

type entity struct {
	myactor.ISuper

	id int32
}

func newEntity(id int32, startedWg *sync.WaitGroup, stoppedWg *sync.WaitGroup) *entity {
	e := &entity{
		id: id,
	}
	e.ISuper = myactor.NewSuper(nil, startedWg, stoppedWg).
		WithOnReceiveMessageHandler(e.onReceiveMessage).
		WithOnStartedHandler(e.onStarted).
		WithOnStoppingHandler(e.onStopping).
		WithOnStoppedHandler(e.onStopped).
		WithOnActorTerminateHandler(e.onActorTerminated)
	return e
}

func (e *entity) Run(ctx actor.Context) (err error) {
	name := fmt.Sprintf("%s-%d", entityName, e.id)
	err = e.ISuper.Start(ctx, name)
	if err != nil {
		return
	}
	e.ISuper.WaitForStarted()
	return
}

func (e *entity) onStarted(ctx actor.Context) {
	//e.Debug("onStarted")
}

func (e *entity) onStopping(ctx actor.Context) {
	//e.Debug("onStopping")
	time.Sleep(util.RandomTimeDuration(100*time.Millisecond, 1000*time.Millisecond))
	//time.Sleep(time.Duration(e.id) * time.Millisecond)
	//time.Sleep(10000 * time.Millisecond)
}

func (e *entity) onStopped(ctx actor.Context) {
	//e.Debug("onStopped")
}

func (e *entity) onReceiveMessage(ctx actor.Context) {
	defer func() {
		if r := recover(); r != nil {
			e.Error("%v\n%s", r, debug.Stack())
			panic(r)
		}
	}()

	sender := ctx.Sender()
	//e.Debug("recv [%#v] from [%v]", ctx.Message(), sender)
	switch msg := ctx.Message().(type) {
	default:
		e.Error("recv unsupported msg [%#v] from [%v]", msg, sender)
	}
}

func (e *entity) onActorTerminated(who *actor.PID, ctx actor.Context) {
	e.Debug("[%s] terminated", who.Id)
}
